(* Copyright (C) 2010 School of Software Engineering, 
 * University of Science and Technology of China.
 *
 * This code is released under a BSD-style license.
 * See the file LICENSE for details.
 *)

structure Control: CONTROL =
struct


structure Verbose =
struct

datatype t 
  = L0
  | L1
  | L2
  | L3

val toInt =
 fn L0 => 0
  | L1 => 1
  | L2 => 2
  | L3 => 3

val op <= =
 fn (x, y) => Int.<= (toInt x, toInt y)

end

datatype verbose = datatype Verbose.t

structure Level =
struct

datatype t 
  = Normal
  | Advanced

end

datatype level = datatype Level.t

datatype opt 
  = String of string -> unit

val expert: bool ref = ref false
val fileName: string ref = ref "<bogus>"
val keepFile: bool ref = ref false
val verbose = ref L0
val diag: string option ref = ref NONE

val currentIndent = ref 0
fun indent () = currentIndent := !currentIndent + 3
fun unIndent () = currentIndent := !currentIndent - 3;
fun getIndent () = !currentIndent

fun spaces (n) =
    if n<0
    then raise Fail "Control.spaces: bug"
    else if n=0 
    then ""
    else String.concat [" ", spaces (n-1)]
    
fun message (name, s) =
    print (String.concat [spaces (getIndent ()),
                          name, s, "\n"])

fun trace (v, name, f) x =
    let val b = Verbose.<= (v, !verbose)       
    in  if b
        then let val _ = message (name, " starts")
                 val _ = indent ()
                 val result = f x
                 val _ = unIndent ()
                 val _ = message (name, " finished")
             in  result
             end
        else f x
    end

fun maySaveToFile (layout: Layout.t, surfix) =
    if (!keepFile)
    then File.output (String.concat [!fileName, ".", surfix], 
                      Layout.toString layout)
    else  ()

val maySaveToFile = trace (L3, "saveToFile", maySaveToFile)

fun pass {v,
          name,
          action,
          display} =
    let val b = Verbose.<= (v, !verbose)
        val result = if b
                     then let val _ = message (name, " starts")
                              val _ = indent ()
                              val result = action ()
                              (*
                              val layout = display result
                              val _ = if (!verbose=L3)
                                      then (Layout.print (Layout.indent (layout, getIndent ())))
                                      else ()
                               *)
                              val _ = unIndent ()
                              val _ = message (name, " finished")
                          in  result
                          end
                     else action ()
        val _ = maySaveToFile (display result, name)
    in  result
    end

end
